home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 22 / Amiga Format AFCD22 (Jan 1998, Issue 106).iso / -in_the_mag- / converters / graphics / netpbm / source1 / pbm / g3topbm.c < prev    next >
C/C++ Source or Header  |  1997-11-16  |  7KB  |  319 lines

  1. /* g3topbm.c - read a Group 3 FAX file and produce a portable bitmap
  2. **
  3. ** Copyright (C) 1989 by Paul Haeberli <paul@manray.sgi.com>.
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. */
  12.  
  13. #include "pbm.h"
  14. #include "g3.h"
  15.  
  16. #define TABSIZE(tab) (sizeof(tab)/sizeof(struct tableentry))
  17. #define MAXCOLS 10800
  18. #define MAXROWS 14400    /* up to two pages long */
  19.  
  20. static int endoffile = 0;
  21. static int eols;
  22. static int rawzeros;
  23. static int shdata;
  24. static int kludge;
  25. static int reversebits;
  26. static int stretch;
  27.  
  28. #define WHASHA 3510
  29. #define WHASHB 1178
  30.  
  31. #define BHASHA 293
  32. #define BHASHB 2695
  33.  
  34. #define HASHSIZE 1021
  35. static tableentry* whash[HASHSIZE];
  36. static tableentry* bhash[HASHSIZE];
  37.  
  38. static void addtohash ARGS(( tableentry* hash[], tableentry* te, int n, int a, int b ));
  39. static tableentry* hashfind ARGS(( tableentry* hash[], int length, int code, int a, int b ));
  40. static int getfaxrow ARGS(( FILE* inf, int row, bit* bitrow ));
  41. static void skiptoeol ARGS(( FILE* file ));
  42. static int rawgetbit ARGS(( FILE* file ));
  43.  
  44. static bit* bits[MAXROWS];
  45.  
  46. int
  47. main( argc, argv )
  48.     int argc;
  49.     char* argv[];
  50.     {
  51.     FILE* ifp;
  52.     int argn, rows, cols, row, col, i;
  53.     char* usage = "[-kludge][-reversebits][-stretch] [g3file]";
  54.  
  55.  
  56.     pbm_init( &argc, argv );
  57.  
  58.     argn = 1;
  59.     kludge = 0;
  60.     reversebits = 0;
  61.     stretch = 0;
  62.  
  63.     /* Check for flags. */
  64.     while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
  65.     {
  66.     if ( pm_keymatch( argv[argn], "-kludge", 2 ) )
  67.         kludge = 1;
  68.     else if ( pm_keymatch( argv[argn], "-reversebits", 2 ) )
  69.         reversebits = 1;
  70.     else if ( pm_keymatch( argv[argn], "-stretch", 2 ) )
  71.         stretch = 1;
  72.     else
  73.         pm_usage( usage );
  74.     argn++;
  75.     }
  76.  
  77.     if ( argn < argc )
  78.     {
  79.     ifp = pm_openr( argv[argn] );
  80.     argn++;
  81.     }
  82.     else
  83.     ifp = stdin;
  84.  
  85.     if ( argn != argc )
  86.     pm_usage( usage );
  87.  
  88.     eols = 0;
  89.  
  90.     if ( kludge )
  91.     {
  92.     /* Skip extra lines to get in sync. */
  93.     skiptoeol( ifp );
  94.     skiptoeol( ifp );
  95.     skiptoeol( ifp );
  96.     }
  97.     skiptoeol( ifp );
  98.     for ( i = 0; i < HASHSIZE; ++i )
  99.     whash[i] = bhash[i] = (tableentry*) 0;
  100.     addtohash( whash, twtable, TABSIZE(twtable), WHASHA, WHASHB );
  101.     addtohash( whash, mwtable, TABSIZE(mwtable), WHASHA, WHASHB );
  102.     addtohash( whash, extable, TABSIZE(extable), WHASHA, WHASHB );
  103.     addtohash( bhash, tbtable, TABSIZE(tbtable), BHASHA, BHASHB );
  104.     addtohash( bhash, mbtable, TABSIZE(mbtable), BHASHA, BHASHB );
  105.     addtohash( bhash, extable, TABSIZE(extable), BHASHA, BHASHB );
  106.  
  107.     cols = 0;
  108.     for ( rows = 0; rows < MAXROWS; ++rows )
  109.     {
  110.     bits[rows] = pbm_allocrow( MAXCOLS );
  111.     col = getfaxrow( ifp, rows, bits[rows] );
  112.     if ( endoffile )
  113.         break;
  114.     if ( !col)
  115.         {
  116.         --rows;
  117.         continue;
  118.         }
  119.     if ( col > cols )
  120.         cols = col;
  121.     if ( stretch )
  122.         {
  123.         bits[rows + 1] = bits[rows];
  124.         ++rows;
  125.         }
  126.     }
  127.  
  128.     pm_close( ifp );
  129.  
  130.     pbm_writepbminit( stdout, cols, rows, 0 );
  131.     for ( row = 0; row < rows; ++row )
  132.     pbm_writepbmrow( stdout, bits[row], cols, 0 );
  133.     pm_close( stdout );
  134.  
  135.     exit(0);
  136.     }
  137.  
  138. static void
  139. addtohash(hash, te, n, a, b)
  140.     tableentry* hash[];
  141.     tableentry* te;
  142.     int n, a, b;
  143. {
  144.     unsigned int pos;
  145.  
  146.     while (n--) {
  147.         pos = ((te->length+a)*(te->code+b))%HASHSIZE;
  148.         if (hash[pos] != 0)
  149.             pm_error( "internal error: addtohash fatal hash collision" );
  150.         hash[pos] = te;
  151.         te++;
  152.     }
  153. }
  154.  
  155. static tableentry*
  156. hashfind(hash, length, code, a, b)
  157.     tableentry* hash[];
  158.     int length, code;
  159.     int a, b;
  160.     {
  161.     unsigned int pos;
  162.     tableentry* te;
  163.  
  164.     pos = ((length+a)*(code+b))%HASHSIZE;
  165.     if (pos < 0 || pos >= HASHSIZE)
  166.     pm_error(
  167.         "internal error: bad hash position, length %d code %d pos %d",
  168.         length, code, pos );
  169.     te = hash[pos];
  170.     return ((te && te->length == length && te->code == code) ? te : 0);
  171.     }
  172.  
  173. static int
  174. getfaxrow( inf, row, bitrow )
  175.     FILE* inf;
  176.     int row;
  177.     bit* bitrow;
  178. {
  179.     int col;
  180.     bit* bP;
  181.     int curlen, curcode, nextbit;
  182.     int count, color;
  183.     tableentry* te;
  184.  
  185.     for ( col = 0, bP = bitrow; col < MAXCOLS; ++col, ++bP )
  186.         *bP = PBM_WHITE;
  187.     col = 0;
  188.     rawzeros = 0;
  189.     curlen = 0;
  190.     curcode = 0;
  191.     color = 1;
  192.     count = 0;
  193.     while (!endoffile) {
  194.         if (col >= MAXCOLS) {
  195.             skiptoeol(inf);
  196.             return (col); 
  197.         }
  198.         do {
  199.             if (rawzeros >= 11) {
  200.                 nextbit = rawgetbit(inf);
  201.                 if (nextbit) {
  202.                     if (col == 0)
  203.                         /* XXX should be 6 */
  204.                         endoffile = (++eols == 3);
  205.                     else
  206.                         eols = 0;
  207. #ifdef notdef
  208.                     if (col && col < 1728)
  209.                         pm_message(
  210.                            "warning, row %d short (len %d)",
  211.                             row, col );
  212. #endif /*notdef*/
  213.                     return (col); 
  214.                 }
  215.             } else
  216.                 nextbit = rawgetbit(inf);
  217.             curcode = (curcode<<1) + nextbit;
  218.             curlen++;
  219.         } while (curcode <= 0);
  220.         if (curlen > 13) {
  221.             pm_message(
  222.       "bad code word at row %d, col %d (len %d code 0x%x), skipping to EOL",
  223.                 row, col, curlen, curcode, 0 );
  224.             skiptoeol(inf);
  225.             return (col);
  226.         }
  227.         if (color) {
  228.             if (curlen < 4)
  229.                 continue;
  230.             te = hashfind(whash, curlen, curcode, WHASHA, WHASHB);
  231.         } else {
  232.             if (curlen < 2)
  233.                 continue;
  234.             te = hashfind(bhash, curlen, curcode, BHASHA, BHASHB);
  235.         }
  236.         if (!te)
  237.             continue;
  238.         switch (te->tabid) {
  239.         case TWTABLE:
  240.         case TBTABLE:
  241.             count += te->count;
  242.             if (col+count > MAXCOLS) 
  243.                 count = MAXCOLS-col;
  244.             if (count > 0) {
  245.                 if (color) {
  246.                     col += count;
  247.                     count = 0;
  248.                 } else {
  249.                     for ( ; count > 0; --count, ++col )
  250.                         bitrow[col] = PBM_BLACK;
  251.                 }
  252.             }
  253.             curcode = 0;
  254.             curlen = 0;
  255.             color = !color;
  256.             break;
  257.         case MWTABLE:
  258.         case MBTABLE:
  259.             count += te->count;
  260.             curcode = 0;
  261.             curlen = 0;
  262.             break;
  263.         case EXTABLE:
  264.             count += te->count;
  265.             curcode = 0;
  266.             curlen = 0;
  267.             break;
  268.         default:
  269.             pm_error( "internal bad poop" );
  270.         }
  271.     }
  272.     return (0);
  273. }
  274.  
  275. static void
  276. skiptoeol( file )
  277.     FILE* file;
  278.     {
  279.     while ( rawzeros < 11 )
  280.     (void) rawgetbit( file );
  281.     for ( ; ; )
  282.     {
  283.     if ( rawgetbit( file ) )
  284.         break;
  285.     }
  286.     }
  287.  
  288. static int shbit = 0;
  289.  
  290. static int
  291. rawgetbit( file )
  292.     FILE* file;
  293.     {
  294.     int b;
  295.  
  296.     if ( ( shbit & 0xff ) == 0 )
  297.     {
  298.     shdata = getc( file );
  299.     if ( shdata == EOF )
  300.         pm_error( "EOF / read error at line %d", eols );
  301.     shbit = reversebits ? 0x01 : 0x80;
  302.     }
  303.     if ( shdata & shbit )
  304.     {
  305.     rawzeros = 0;
  306.     b = 1;
  307.     }
  308.     else
  309.     {
  310.     rawzeros++;
  311.     b = 0;
  312.     }
  313.     if ( reversebits )
  314.     shbit <<= 1;
  315.     else
  316.     shbit >>= 1;
  317.     return b;
  318.     }
  319.